const express = require('express')
const app = express()
// 用于处理 multipart/form-data 类型的表单数据，它主要用于上传文件。
const multer = require('multer')
// 数据库
const { Lose, Collection, User, Advice, Admin } = require('./db')
const { v4 } = require('uuid')
const axios = require('axios')
// 使用中间件解决get请求问题
app.use(express.urlencoded({ extended: true }));
app.use(express.json())
app.use(express.static(__dirname))

app.all('*', (req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader("Access-Control-Allow-Headers", "*");
  next()
})

// 这是一个用于将文件保存在服务器文件系统上的存储策略。
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    // 定义文件存储的路径
    cb(null, "./file/")
  },
  filename: (req, file, cb) => {
    // 定义文件的名称 
    // 使用uuid生成文件名，并去除文件扩展名
    let type = file.originalname.replace(/.+\./, ".");
    // 返回生成的文件名
    cb(null, `${v4()}${type}`);
  }
})
// 创建multer实例
const upload = multer({ storage });


// --------------------------------------------小程序部分----------------------------------------------------------
// 获取发布信息,将信息存入Lose数据表里
app.post('/publish', async (req, res) => {
  try {
    const { type, classify1, classify2, name, date, region, phone, desc, imgList, time, openid } = req.body;
    if (imgList.length === 0) {
      imgList.push('http://localhost:80/file/moren.jpg')
    }
    await Lose.create({
      type, classify1, classify2, name, date, region, phone, desc, imgList, time, openid
    })
    res.send('success')
  } catch (error) {
    res.send(error)
  }
})
// 创建上传图片的接口
app.post("/uploadImg", upload.array("file", 6), (req, res) => {
  res.send(req.files)
})

// 获取首页的数据
app.get('/getLose', async (req, res) => {
  const { type } = req.query
  const result = await Lose.find({
    type
  }).sort({
    time: -1
  })
  res.send(result)
})

// 查询当前物品有没有被当前这个人收藏过
app.post("/checkCollection", async (req, res) => {
  try {
    const { id, openid } = req.body
    const result = await Collection.find({
      id,
      openid
    })
    res.send(result)
  } catch (error) {
    res.send(error)
  }

})

// 认领
app.post('/toClaim', async (req, res) => {
  try {
    const { desc, img_list, openid, _id } = req.body
    await Lose.findByIdAndUpdate(_id, {
      claimInfo: {
        desc, img_list, openid
      },
      state: 1
    })
    res.send("success")
  } catch (error) {
    console.log(error)
  }
})

// 收藏物品
app.post('/toCollection', async (req, res) => {
  try {
    const { id, openid } = req.body;
    await Collection.create({
      id, openid
    })
    res.send('success')
  } catch (error) {
    res.send('error')
  }
})

// 取消收藏
app.post('/cancelCollection', async (req, res) => {
  try {
    const { id, openid } = req.body
    await Collection.findOneAndDelete({
      id, openid
    })
    res.send("success")
  } catch (error) {
    res.send(error)
  }
})

// 获取收藏夹的数据
app.post('/getCollection', async (req, res) => {
  const { openid, type } = req.body
  const result = await Collection.find({
    openid
  }).populate(
    'id'
    // 在populate时添加match条件来筛选Lose表中的type
  );
  const _result = result.filter(item => item.id.type === type)
  res.send(_result)
  // populate是将查询结果中的id字段替换成所引用的Lose表中相应ID的数据
})

// 获取我发布的数据
app.get('/getMyPublih', async (req, res) => {
  const { openid, type } = req.query
  const result = await Lose.find({
    openid,
    type
  })
  res.send(result)
})

// 通过二级分类查数据
app.post('/getClassifyTwo', async (req, res) => {
  const { type, classify2 } = req.body
  const result = await Lose.find({
    type,
    classify2
  })
  res.send(result)
})


// 模糊查询物品名字
app.get("/searchLose", async (req, res) => {
  const { name, type } = req.query
  //  RegExp 是JavaScript中正则表达式的构造函数。通过使用 new 关键字，可以创建一个正则表达式对象。
  // RegExp(name,'i') name是要匹配的，i是不分大小写
  const _name = new RegExp(name, 'i')
  let result = null
  if (type) {
    result = await Lose.find({
      name: _name,
      type
    })
  } else {
    result = await Lose.find({
      name: _name,
    })
  }

  res.send(result)
})

// 实现登陆操作
app.get("/login", async (req, res) => {
  try {
    const { code } = req.query;
    //  通过小程序的接口，获取用户的openid,openid可以获取授权用户的头像、名称等
    const { data: { openid }
    } = await axios.get(`https://api.weixin.qq.com/sns/jscode2session?appid=wx03e28aed0608e610&secret=b64368fc3e688e1ef8bf776aa4be8b8b&js_code=${code}&grant_type=authorization_code`)

    res.send(openid)
  } catch (error) {
    res.send("error")
  }

})

// 小程序删除寻物/寻主数据
app.post('/deleteLose', async (req, res) => {
  const { _id } = req.body
  try {
    await Lose.findByIdAndDelete(_id)
    // 删除时吧收藏夹的也删除了
    await Collection.findOneAndDelete({
      id: _id
    })
    res.send('success')
  } catch (error) {
    res.send('error')
  }
})

// 查询物品详情数据
app.post('/getDetail', async (req, res) => {
  const { _id } = req.body
  try {
    const result = await Lose.findById({ _id })
    res.send(result)
  } catch (error) {
    res.send('error')
  }
})

// 小程序修改数据
app.post('/updateLose', async (req, res) => {
  const { type, classify1, classify2, name, date, region, phone, desc, imgList, time, openid, id } = req.body
  try {
    await Lose.findByIdAndUpdate(id, {
      type, classify1, classify2, name, date, region, phone, desc, imgList, time, openid
    })
    res.send('success')
  } catch (error) {
    res.send('error')
  }
})

// 意见反馈
app.post('/addAdvice', async (req, res) => {
  try {
    const { phonenumber, advice_content, openid } = req.body;
    await Advice.create({
      phonenumber,
      advice_content,
      openid,
      create_time: new Date().getTime()
    })
    res.send('success')
  } catch (error) {
    res.send('error')
  }
})

// 查询是否登陆过
app.post('/searchLogin', async (req, res) => {
  const { openid } = req.body
  const result = await User.findOne({
    openid
  })
  if (result) {
    res.send("exist")
  } else {
    res.send("first")
  }
})

// 第一次登陆
app.post('/firstLogin', async (req, res) => {
  const { openid, avatarurl, nickname } = req.body
  try {
    await User.create({
      openid,
      avatarurl,
      nickname
    })
    res.send("success")
  } catch (error) {
    res.send("error")
  }
})
// 再次登陆
app.post('/existLogin', async (req, res) => {
  const { openid } = req.body
  try {
    const result = await User.findOne({
      openid
    })
    res.send(result)
  } catch (error) {
    res.send("error")
  }
})
// 更改头像
app.post('/updateimg', async (req, res) => {
  const { openid, avatarurl } = req.body
  try {
    await User.findOneAndUpdate(
      { openid: openid }, //查询的
      { avatarurl: avatarurl }//更改的
    )
    res.send('success')
  } catch (error) {
    res.send('error')
  }
})
// 更改昵称
app.post('/updatenickname', async (req, res) => {
  const { openid, nickname } = req.body
  try {
    await User.findOneAndUpdate({ openid: openid }, {
      nickname: nickname
    })
    res.send('success')
  } catch (error) {
    res.send('error')
  }
})

// 更改联系方式
app.post('/updatecontact', async (req, res) => {
  const { openid, contact } = req.body
  try {
    await User.findOneAndUpdate({ openid: openid }, {
      contact: contact
    })
    res.send('success')
  } catch (error) {
    res.send('error')
  }
})

// 返回更新后的数据
app.post('/update', async (req, res) => {
  const { openid } = req.body
  try {
    const result = await User.findOne({ openid })
    res.send(result)
  } catch (error) {
    res.send('error')
  }
})

// 提交评论
app.post('/addComment', async (req, res) => {
  const { avatarUrl, nickName, content, time, _id } = req.body
  try {
    let result = await Lose.findById(_id)
    let { commentList } = result
    commentList.unshift({
      avatarUrl, nickName, content, time
    })
    await Lose.findByIdAndUpdate(_id, {
      commentList
    })
    result["commentList"] = commentList
    res.send({ status: "success", data: result })
  } catch (error) {
    res.send({ status: "error", error })
  }
})


// --------------------------------------------后台管理系统部分----------------------------------------------------------
app.post('/admin/login', async (req, res) => {
  const { username, password } = req.body
  const result = await Admin.findOne({ username })
  if (result && result.password === password) {
    // 登录成功
    res.send(result)
  } else {
    // 登录失败
    res.send('error')
  }
})

// 寻主/寻物
app.post('/admin/getLose', async (req, res) => {
  const { type, page, size } = req.body
  // skip是要跳过多少条数据。page是当前页数,size是页面有几条数据
  try {
    const result = await Lose.find({ type }).skip((page - 1) * size).limit(size)
    const total = await Lose.find({ type }).countDocuments()
    res.send({ result, total })
  } catch (error) {
    res.send('error')
  }
})


// ------------------------------------------------------------------------------------------------------------------------------
app.listen(80, () => {
  console.log('serve is running')
})